package cas.server.userinfo;

import cas.client.User;
import cas.server.DB;
import cas.server.SecurityKey;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Instant;

@WebServlet(name = "UserInfoAPIServlet", urlPatterns = "/user-info-api")
public class UserInfoAPIServlet extends HttpServlet {

    // 验证token，返回用户信息
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String token = request.getHeader("Authorization");
        if (token == null || token.isEmpty()) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            return;
        }
        try {
            User result = authenticateToken(token);
            ObjectMapper objectMapper = new ObjectMapper();
            objectMapper.writeValue(response.getOutputStream(), result);
        } catch (SQLException e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

    // 验证token，返回用户信息
    private static User authenticateToken(String token) throws SQLException {
        Claims claims = getClaims(token);
        if (claims != null) {
            if (compareToken(claims)) {
                if (Instant.now().isBefore(claims.getExpiration().toInstant())) {
                    return getUserInfo(claims.getSubject());
                }
            }
        }
        return null;
    }

    // 获取JWT的负载信息
    private static Claims getClaims(String token) {
        try {
            return Jwts.parser()
                    .verifyWith(SecurityKey.getKeyPair().getPublic())
                    .build()
                    .parseSignedClaims(token)
                    .getPayload();
        } catch (JwtException e) {
            return null;
        }
    }

    // 对比数据库中存储的token
    private static boolean compareToken(Claims claims) throws SQLException {
        String account = claims.getSubject();
        Timestamp issueAt = Timestamp.from(claims.getIssuedAt().toInstant());
        Timestamp expiration = Timestamp.from(claims.getExpiration().toInstant());
        boolean[] result = {false};
        DB.query(resultSet -> result[0] = resultSet.next(), "SELECT account FROM token WHERE account = ? AND issued_at = ? AND expiration = ?", account, issueAt, expiration);
        return result[0];
    }

    // 获取用户信息
    private static User getUserInfo(String account) throws SQLException {
        User result = new User();
        DB.query(resultSet-> {
            resultSet.next();
            result.setAccount(account);
            result.setAge(resultSet.getInt(1));
            result.setGender(resultSet.getString(2));
        }, "SELECT age, gender FROM user WHERE account = ?", account);
        return result;
    }
}
